#pragma once

#include <iostream>
#include <string>
#include <cstring>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h> // 添加 errno 头文件以使用 errno

const int gfd = -1;

// 命名管道文件名字
#define FIFO_FILE "fifo"
#define BUFFER_SIZE 1024
#define PATH "."
#define FILENAME "fifo"

#define ERR_EXIT(m)         \
    do                      \
    {                       \
        perror(m);          \
        exit(EXIT_FAILURE); \
    } while (0)

class FIFOFile
{
public:
    FIFOFile(const std::string &path, const std::string &file)
        : _path(path), _file(file)
    {
        _filename = _path + '/' + _file;
        int fifoid = mkfifo(_filename.c_str(), 0666); // 使用正确的路径和权限
        if (fifoid == -1 && errno != EEXIST)
        { // 检查 mkfifo 的返回值
            ERR_EXIT(_filename.c_str());
        }
        else
        {
            std::cout << "mkfifo success!" << std::endl;
        }
    }

    ~FIFOFile()
    {
        int ret = unlink(_filename.c_str()); // 使用 _filename.c_str() 而不是 _file.c_str()
        if (ret < 0)
        {
            ERR_EXIT("unlink");
        }
        else
        {
            std::cout << "unlink success!" << std::endl;
        }
    }

private:
    std::string _path;
    std::string _file;
    std::string _filename;
};

class FIFOFileOperation
{
public:
    FIFOFileOperation()
        : _fd(gfd), _path(""), _file(""), _filename("")
    {
    }

    FIFOFileOperation(const std::string &path, const std::string &file)
        : _fd(gfd), _path(path), _file(file)
    {
        _filename = _path + '/' + _file;
    }

    void OpenforRead()
    {
        _fd = open(_filename.c_str(), O_RDONLY);
        if (_fd < 0)
        {
            ERR_EXIT("OpenforRead");
        }
        else
        {
            std::cout << "OpenforRead success!" << std::endl;
        }
    }

    void OpenforWrite()
    {
        _fd = open(_filename.c_str(), O_WRONLY);
        if (_fd < 0)
        {
            ERR_EXIT("OpenforWrite");
        }
        else
        {
            std::cout << "OpenforWrite success!" << std::endl;
        }
    }

    void Read()
    {
        while (true)
        {
            char buffer[BUFFER_SIZE];
            ssize_t n = read(_fd, buffer, sizeof(buffer) - 1);
            if (n < 0)
            {
                ERR_EXIT("Read");
            }
            else if (n == 0)
            {
                std::cout << "Client exit! Me too!" << std::endl;
                break; // 读取到0字节表示客户端关闭，退出循环
            }
            else
            {
                buffer[n] = 0;
                std::cout << buffer << std::endl;
            }
        }
    }

    void Write()
    {
        while (true)
        {
            std::cout << "Please input your message# ";
            std::string buffer;
            std::getline(std::cin, buffer);
            int cnt = 1;
            buffer += " " + std::to_string(cnt++);
            ssize_t n = write(_fd, buffer.c_str(), buffer.size());
            if (n < 0)
            {
                ERR_EXIT("Write");
            }
            else
            {}
        }
    }

    void Close()
    {
        if (_fd != -1) // 检查文件描述符是否有效
        {
            close(_fd);
            _fd = -1; // 关闭后将文件描述符重置为-1
        }
    }

    ~FIFOFileOperation()
    {
        Close(); // 析构函数中调用Close方法确保文件描述符被关闭
    }

private:
    std::string _path;
    std::string _file;
    std::string _filename;
    int _fd;
};